<?php
// Класс объекта-переключателя
class switch_loader
{
	// Буфер с выводом клиентского модуля
	var $buf='';
	// Флаг начала захвата буфера
	var $ob_start = false;
	// Имя модуля 'shell'
	var $MT_mod_name = null;
	// Имя модуля, которому принадлежит branch
	var $branch_MT_mod_name = null;
	// Имя ветки
	var $branch_name = null;
	// Стек шаблонов
	var $tmlstack;
	// Флаги
	// Без шаблонов
	var $tf_notemplates=true;
	// Запретить установку шаблонов
	var $tf_forbid=false;
	// id последнего добавленного шаблона
	var $tf_lasttemplate=null;
	// utl для редиректа
	var $tf_redirect=null;
	// Родительский Switch
	var $parent_Shell = null;
	function __construct($MT_mod_name,$parent_Shell=null)
	{
		if (empty($MT_mod_name))
		{
			// Ошибка
			mst_error('Ошибка инициализации',
                "Объект swhitcher требует имя модуля для инициализации",1);
		}
		if (is_object($parent_Shell))
		{
			$this->parent_Shell = $parent_Shell;
		}
		$this->MT_mod_name = $MT_mod_name;
		$this->tmlstack = array();
		//
	}
	function getswitcher($urlmaker,$disp=0,$path=null)
	{
		$bswitcher = new switch_bswitcher($this,$urlmaker,$path,$disp,0);
		return $bswitcher;
	}
	function loadfile($branch_MT_mod_name,$branch,$file,$branch_switcher,
						$MT_mod_cust=NULL)
	{
		// echo $this->MT_mod_name;
		// Сохраняем имя модуля, которому принадлежит branch
		$this->branch_MT_mod_name = $branch_MT_mod_name;
		// Сохраняем имя ветки
		$this->branch_name = $branch;

		$MT_mod_cust['Switcher'] = $branch_switcher;
		// Начинаем перехватывать буфер вывода
		if (!$this->ob_start())
		{
			// Ошибка
			mst_error('Невозможно загрузить branch',
                "Текущий переключатель уже обрабатывает один branch",1);
		}
		mst_modfileload($branch_MT_mod_name,
						'switch/'.$branch.'/'.$file,
						$MT_mod_cust);
		// Сохраняем буфер вывода
		$this->ob_stop();
		return true;
	}
	function process($branch_MT_mod_name,$branch,$file,$disp,
						$urlmaker,$branch_path=null,$MT_mod_cust=NULL,
						$return_text=false)
	{
		// Стандартная обработка branch
		// Создаем объект-указатель
		$branch_switcher = $this->getswitcher($urlmaker,$disp,$branch_path);
		// Загружаем файл с бизнес-логикой
		$this->loadfile($branch_MT_mod_name,$branch,$file,$branch_switcher,
						$MT_mod_cust);
		// Применяем шаблоны оформления
		$this->apptemplates($branch_switcher);
		// Выводим результат
		if ($return_text)
		{
			return $this->ob_get();
		}else
		{
			echo $this->ob_get();		
			return true;
		}
	}
	/**
	 * Исполнить вложенный branch	
	 * @param $branch_MT_mod_name - имя модуля, которому принадлежит branch
	 * @param $branch - имя branch
	 * @param $file - запускаемый файл в branch
	 * @param $disp - смещение относительно начала пути
	 * @param $urlvar - имя переменной со ссылкой
	 * @param $branch_path - принудительно заданный путь
	 * @param $MT_mod_cust - параметры, передаваемые в branch
	 * @param $return_text - вернуть контент в виде текста
	 * @return mix
	 */
	function subswitch($branch_MT_mod_name,$branch,$file,$disp,
						$urlmaker,$branch_path=null,$MT_mod_cust=NULL,
						$return_text=false)
	{
		// Создаем дочерний переключатель
		$Shell = new switch_loader($this->MT_mod_name,$this);
		// Обрабатываем файл с бизнес-логикой
		return $Shell->process($branch_MT_mod_name,$branch,$file,$disp,
						$urlmaker,$branch_path,$MT_mod_cust,$return_text);
	}
	function apptemplates($branch_switcher)
	{
		// Применяем все действующие шаблоны оформления
		if ($this->tf_notemplates OR !$this->tmlstack)
		{
			// Шаблон не применяется
			return false;
		}elseif(empty($this->tmlstack))
		{
			// Ни один шаблон не определен
			return false;
		}else
		{
			// По очереди запускаем все шаблоны в обратном порядке
			// Ставим указатель на конец массива
			end($this->tmlstack);
			// Получаем последний элемент
			$tml = current($this->tmlstack);
			do
			{
				// Обрабатываем шаблон
				$this->apptemplate($branch_switcher,
									$tml['runer'],
									$tml['mod'],
									$tml['file'],
									$tml['vars'],
									$tml['flags'],
									$tml['lists']);
				
			}while($tml = prev($this->tmlstack));
		}
		return true;
	}
	// Применяем шаблон оформления
	private function apptemplate($branch_switcher,$tmlruner,$tmlmod,$tmlfile,$tmlvars,$tmlflags,$tmllists)
	{
		if (strlen($tmlruner)==0)
		{
			//
			mst_error('Обработчик шаблонов не найден',
                "Не передано имя обработчика для шаблона ({$tmlfile}) в модуле ({$tmlmod})",1);
            return false;
		}
		// Останавливаем захват буфера, если еще не остановлен
		$this->ob_stop();
		// Инициализируем обработчик шаблонов
		mst_modfileload($this->MT_mod_name,'tmlruners/'.$tmlruner.'.php',null,true);
		// Вызываем обработчик шаблонов
		$tmlexecuter = 'switch_template_'.$tmlruner;
		if (!function_exists($tmlexecuter))
		{
			// Обработчик отсутствует
			mst_error('Обработчик шаблонов не найден',
                "Не найден обработчик шаблонов {$tmlexecuter} для шаблона ({$tmlfile}) в модуле ({$tmlmod})",2);
            return false;
		}
		// Задаем собственные переменные-огружения шаблона
		$tmlvars['switch-url-themes'] = mst_url('THEMES');
		// Вызываем обработчик шаблона и сохраняем результат в буфер вывода
		$this->buf = $tmlexecuter($tmlmod,'tml/'.$tmlfile,$this->buf,$tmlvars,$branch_switcher,$tmlflags,$tmllists);
		return true;
	}
	/**
	 * Вернуть информацию из буфера
	 */
	function ob_get()
	{
		return $this->buf;
	}
	/**
	 * Немедленно остановить захват буфера и выдать результат в браузер
	 */
	function ob_flush()
	{
		//  Останавливаем захват буфера, если был начат
		$this->ob_stop();
		// Выводим захваченные данные
		echo $this->buf;
		// Принудительно отправляем текущий буфер пользователю
		
	}
	/**
	 * Начать захват буфера вывода
	 */
	function ob_start()
	{
		if ($this->ob_start)
		{
			// Ошибка
			return false;
		}
		// Начинаем перехватывать буфер вывода
		ob_start();
		$this->ob_start = true;
		return true;
	}
	/**
	 * Закончить захват буфера вывода
	 */
	function ob_stop()
	{
		if (!$this->ob_start)
		{
			// Ошибка
			return false;
		}
		// Сохраняем буфер вывода
		$this->buf = ob_get_contents();
		// Очищаем буфер вывода
		ob_end_clean();
		$this->ob_start = false;
		return true;
	}
	/**
	 * Возвращает true, если это первый уровень захвата буфера	
	 * @return boolean
	 */
	function ob_ismain()
	{
		return true;
	}
	// Добавть шаблон в стек
	function tml_add($runer,$mod,$file,$vars=null,$flags=null,$lists=null)
	{
		if ($this->tf_forbid)
		{
			// Установка шабонов запрещена
			return false;
		}
		if (strlen($runer)==0 OR strlen($mod)==0 OR strlen($file)==0)
		{
			// Не переданы необходимые параметры
			return false;
		}
		// Разрешаем обработку шаблонов
		$this->tf_notemplates = false;
		// Если переменные шаблона не заданы - пустой массив
		if (is_null($vars)){$vars=array();}
		if (is_null($flags)){$flags=array();}
		if (is_null($lists)){$lists=array();}
		// Добавляем шаблон в стек
		$this->tmlstack[] = array(
								'runer'=>$runer,
								'mod'=>$mod,
								'file'=>$file,
								'vars'=>$vars,
								'flags'=>$flags,
								'lists'=>$lists
								);
		// Сохраняем и возвращаем id добавленного шаблона
		end($this->tmlstack);
		return $this->tf_lasttemplate = key($this->tmlstack);
	}
	// Сбросить стек
	function tml_reset($runer,$mod,$file,$vars=null,$recurse=false,$flags=null,$lists=null)
	{
		if ($this->tf_forbid)
		{
			// Установка шабонов запрещена
			return false;
		}
		// Отключаем обработку шаблонов в вышестоящих branch
		if ($recurse AND is_object($this->parent_Shell))
		{
			$this->parent_Shell->tml_off(true);
		}
		// Разрешаем обработку шаблонов
		$this->tf_notemplates = false;
		// Очищаем стек шаблонов
		$this->tmlstack = array();
		
		// Если переменные шаблона не заданы - пустой массив
		if (is_null($vars)){$vars=array();}
		if (is_null($flags)){$flags=array();}
		if (is_null($lists)){$lists=array();}
		// Добавляем шаблон в стек
		$this->tmlstack[1] = array(
								'runer'=>$runer,
								'mod'=>$mod,
								'file'=>$file,
								'vars'=>$vars,
								'flags'=>$flags,
								'lists'=>$lists
								);
		// Сохраняем и возвращаем id добавленного шаблона
		end($this->tmlstack);
		return $this->tf_lasttemplate = key($this->tmlstack);
	}
	// Отключить обработку шаблонов
	function tml_off($recurse=false,$forbid=false)
	{
		// Отключаем обработку шаблонов
		$this->tf_notemplates = true;
		// Запрещаем добавление шаблонов
		$this->tf_forbid = $forbid;
		// Обнуляем стек шаблонов
		$this->tmlstack = array();
		if ($recurse AND is_object($this->parent_Shell))
		{
			$this->parent_Shell->tml_off(true,$forbid);
		}
		return true;
	}
	// Вместо обработки шаблона отправить заголовки для редиректа по url
	function tml_redirect($msturl)
	{
		//
		if ('REFERER'==$msturl)
		{
			$msturl = $_SERVER["HTTP_REFERER"];
		}
		// Запрещаем обработку шаблонов рекурсивно
		$this->tml_off(true,true);
		// Устанавливаем редирект для перехода
		$this->tf_redirect = $msturl;
		// Отправляем заголовки для перехода
		header("Location: {$msturl}");
		return true;
	}
	function tml_mime($content_type,$tml_off=false,$download_file=null)
	{
		if ($tml_off)
		{
			// Отключаем и запрещаем шаблоны
			$this->tml_off(true,true);
		}
		// Отправлеям заголовки с content-типом
		header("Content-type: {$content_type}",true);
		// echo "Content-type: {$content_type}";
		if (!is_null($download_file))
		{
			//
			header('Content-Disposition: attachment; filename="'.$download_file.'"');
		}
		return true;
	}
	/**
	 * Передать переменную в шаблон	
	 * @param $varname
	 * @param $value
	 * @param $template_id
	 * @return int
	 */
	function tml_setvar($varname,$value,$template_id=null)
	{
		//
		if (is_null($template_id))
		{
			// ID шаблона не передано и мы добавляем переменную
			// в последний добавленный
			$template_id = $this->tf_lasttemplate;
		}
		if (is_null($template_id) OR !is_array($this->tmlstack[$template_id]))
		{
			// Ошибка
			mst_error('Шаблон не установлен',
                "Невозможно передать переменную ({$varname}) в шаблон ({$template_id}), так как",2);
			return false;
		}
		$this->tmlstack[$template_id]['vars'][$varname]=$value;
		return $template_id;
	}
	function get_branchmod()
	{
		return $this->branch_MT_mod_name;
	}
	function get_branchname()
	{
		return $this->branch_name;
	}
}

?>